--------------------------------------------------------------------------------------
-- Variables and Constants -----------------------------------------------------------
--------------------------------------------------------------------------------------

LYLOCK_VERSION = "v2.5.0"
LYLOCK_DISABLE = false

LyLock_Plugins = {}
LyLock_Settings = {}
LyLock_Defaults = {}
LyLock_PlayerName = UnitName("player")

LYLOCK_FLAGCAST = "X"
LYLOCK_FLAGMAKE = "C"
LYLOCK_FLAGNONE = ""

TEXTURE_SOULSHARD = "Spell_Shadow_SoulGem"
TEXTURE_BANISH = "Spell_Shadow_Cripple"
TEXTURE_DEMONARMOR = "Spell_Shadow_RagingScream"
TEXTURE_SOULSTONE = "Spell_Shadow_SoulGem"
TEXTURE_FELARMOR = "Spell_Shadow_FelArmour"

--------------------------------------------------------------------------------------
-- Settings Functions ----------------------------------------------------------------
--------------------------------------------------------------------------------------

function LyLock_SettingsFrameAction(action)
    MissingOptionsFrame:Hide();
    
    if action=="Open" then LyLock_OnSettings("load"); LyLockConfigFrame:Show(); end
    if action=="Open" or action=="Visual" then VisualOptionsFrame:Show(); else VisualOptionsFrame:Hide(); end
        
    LyLock_SettingsFrameChange(SummonOptionsFrame, (action=="Summon"))
    LyLock_SettingsFrameChange(ArmorOptionsFrame, (action=="Armor"))
    LyLock_SettingsFrameChange(HealthstoneOptionsFrame, (action=="Healthstone"))
    LyLock_SettingsFrameChange(SoulstoneOptionsFrame, (action=="Soulstone"))
    LyLock_SettingsFrameChange(SoulShardOptionsFrame, (action=="SoulShard"))
    LyLock_SettingsFrameChange(BanishOptionsFrame, (action=="Banish"))
        
    if action=="Confirm" then LyLock_OnSettings("save"); end
    if action=="Cancel" or action=="Confirm" then
        LyLockConfigFrame:Hide();
        LyLock_ApplyVisualSettings()
    end
end

function LyLock_SettingsFrameChange(frame, show)
    if show then
        if (frame~=nil) then frame:Show(); else MissingOptionsFrame:Show(); end
   else
        if (frame~=nil) then frame:Hide(); end
    end
end

function LyLock_OnSettings(action)
    if (action=="default") then
        localizedClass, englishClass = UnitClass("player")
        
        LYLOCK_DISABLE = (englishClass ~= "WARLOCK")
        ENABLE_DEBUG = (LyLock_PlayerName=="Andload")
        
        if LYLOCK_DISABLE then
            DEFAULT_CHAT_FRAME:AddMessage("|CFFFF0000ATTENTION!!!! LyLock is disabling because this character is not a warlock.  However it is a better idea to disable this add-on for this character from the add-on screen as it will save a little memory during game play.")
            LyLockFrame:Hide();
            return false
        else
            ------------------------------------------------------
            -- Configuration Settings ----------------------------
            ------------------------------------------------------

            LyLock_Settings.Visual_DisableBar = ReturnSetting(LyLock_Settings.Visual_DisableBar, false)
            LyLock_Settings.Visual_LockFrames = ReturnSetting(LyLock_Settings.Visual_LockFrames, true)
            LyLock_Settings.Visual_ColorScheme = ReturnSetting(LyLock_Settings.Visual_ColorScheme, "Wings")
            
            LyLock_Settings.Visual_VerticalBar = ReturnSetting(LyLock_Settings.Visual_VerticalBar, false)
            LyLock_Settings.Visual_ButtonSize = ReturnSetting(LyLock_Settings.Visual_ButtonSize, 33)
            LyLock_Settings.Visual_ButtonSpace = ReturnSetting(LyLock_Settings.Visual_ButtonSpace, 6)
            LyLock_Settings.Visual_ButtonText = ReturnSetting(LyLock_Settings.Visual_ButtonText, true)
            LyLock_Settings.Visual_FontSize = ReturnSetting(LyLock_Settings.Visual_FontSize, 10)
        end
    elseif (action=="save") then
        if Visual_ColorSchemePinky:GetChecked() then
            LyLock_Settings.Visual_ColorScheme = "Pinky"
        elseif Visual_ColorSchemeWings:GetChecked() then
            LyLock_Settings.Visual_ColorScheme = "Wings"
        elseif Visual_ColorSchemeBlast:GetChecked() then
            LyLock_Settings.Visual_ColorScheme = "Blast"
        elseif Visual_ColorSchemeTrees:GetChecked() then
            LyLock_Settings.Visual_ColorScheme = "Trees"
        end
        
        LyLock_Settings.Visual_DisableBar = iif(Visual_DisableBar:GetChecked(), true, false);
        LyLock_Settings.Visual_VerticalBar = iif(Visual_VerticalBar:GetChecked(), true, false);
        LyLock_Settings.Visual_ButtonSize = Visual_ButtonSize:GetValue();
        LyLock_Settings.Visual_ButtonSpace = Visual_ButtonSpace:GetValue();
        LyLock_Settings.Visual_ButtonText = iif(Visual_ButtonText:GetChecked(), true, false);
        LyLock_Settings.Visual_FontSize = Visual_FontSize:GetValue();
    elseif (action=="load") then
        Visual_ColorSchemePinky:SetChecked(LyLock_Settings.Visual_ColorScheme == "Pinky");
        Visual_ColorSchemeWings:SetChecked(LyLock_Settings.Visual_ColorScheme == "Wings");
        Visual_ColorSchemeBlast:SetChecked(LyLock_Settings.Visual_ColorScheme == "Blast");
        Visual_ColorSchemeTrees:SetChecked(LyLock_Settings.Visual_ColorScheme == "Trees");

        Visual_DisableBar:SetChecked(LyLock_Settings.Visual_DisableBar);
        Visual_VerticalBar:SetChecked(LyLock_Settings.Visual_VerticalBar);
        Visual_ButtonSize:SetValue(LyLock_Settings.Visual_ButtonSize);
        Visual_ButtonSpace:SetValue(LyLock_Settings.Visual_ButtonSpace);
        Visual_ButtonText:SetChecked(LyLock_Settings.Visual_ButtonText);
        Visual_FontSize:SetValue(LyLock_Settings.Visual_FontSize);
    end

    for i, p in pairs(LyLock_Plugins) do
        if (p.OnSettings~=nil) then p.OnSettings(action) end
    end    
        
    return true
end


function LyLock_ApplyVisualSettings()
    SetColorScheme(LyLock_Settings.Visual_ColorScheme)
    SetActionBarPos(LyLock_Settings.Visual_DisableBar, LyLock_Settings.Visual_VerticalBar, LyLock_Settings.Visual_ButtonSize, LyLock_Settings.Visual_ButtonSpace)
    SetActionBarFont(LyLock_Settings.Visual_FontSize, LyLock_Settings.Visual_ButtonText)
end

function SetColorScheme(scheme)
    scheme=string.lower(scheme)
    if scheme=="pinky" then
        COLOR_NORMAL ="|CFFFFFFFF"
        COLOR_ERROR = "|CFFFF00FF"
        COLOR_HEADER = "|CFFFF99FF"
        COLOR_VALUE = "|CFFFF99FF"
        COLOR_NOTIFY = "|CFFFFC4FF"
        COLOR_TITLE = "|CFFFF50FF"
        COLOR_BRACKET = "|CFFB700B7"
    elseif scheme=="blast" then
        COLOR_NORMAL = "|CFFFFFFFF"
        COLOR_ERROR = "|CFFFF6600"
        COLOR_HEADER = "|CFFFFCC00"
        COLOR_VALUE = "|CFFFFCC00"
        COLOR_NOTIFY = "|CFFFFD387"
        COLOR_TITLE = "|CFFFF3300"
        COLOR_BRACKET = "|CFFDE8800"
    elseif scheme=="trees" then
        COLOR_NORMAL = "|CFFFFFFFF"
        COLOR_ERROR = "|CFF00FF00"
        COLOR_HEADER = "|CFF81FF43"
        COLOR_VALUE = "|CFF81FF43"
        COLOR_NOTIFY = "|CFFCCFF66"
        COLOR_TITLE = "|CFF00FA00"
        COLOR_BRACKET = "|CFFFFFF66"
    elseif scheme=="wings" then
        COLOR_NORMAL = "|CFFEBEBFF"
        COLOR_ERROR = "|CFF4040FF"
        COLOR_HEADER = "|CFF8080FF"
        COLOR_VALUE = "|CFF8080FF"
        COLOR_NOTIFY = "|CFFC0C0FF"
        COLOR_TITLE = "|CFF2065C2"
        COLOR_BRACKET = "|CFF01059D"
    end
end

function SetActionBarPos(disable, vert, size, space)
    local last = LyLockActionBar
    last = SetActionButtonPos(LyLockSummonButton, ((not disable) and LyLock_Settings.Summon_Button), last, vert, size, space)
    last = SetActionButtonPos(LyLockArmorButton, ((not disable) and LyLock_Settings.Armor_Button), last, vert, size, space)
    last = SetActionButtonPos(LyLockHealthstoneButton, ((not disable) and LyLock_Settings.Healthstone_Button), last, vert, size, space)
    last = SetActionButtonPos(LyLockSoulstoneButton, ((not disable) and LyLock_Settings.Soulstone_Button), last, vert, size, space)
    last = SetActionButtonPos(LyLockSoulShardButton, ((not disable) and LyLock_Settings.SoulShard_Button), last, vert, size, space)
end

function SetActionButtonPos(frame, show, last, vert, size, space)
    if (frame~=nil) then
        frame:SetWidth(size+2);
        frame:SetHeight(size+2);
        local point, sub, to, offsetx, offsety = frame:GetPoint();
        if show then
            if vert then
                frame:SetPoint(point, last, to, 0, (-space) + size);
            else
                frame:SetPoint(point, last, to, space + size, 0);
            end
            frame:Show();
            last = frame;
        else
            frame:Hide();
        end
    end
    return last;
end

function SetActionBarFont(size, visible)
    SetActionBarFont2(LyLockArmorReadyText, size, visible)
    SetActionBarFont2(LyLockHealthstoneCooldownText, size, visible)
    SetActionBarFont2(LyLockSoulstoneCooldownText, size, visible)
    SetActionBarFont2(LyLockSoulShardCountText, size, visible)
end

function SetActionBarFont2(frame, size, visible)
    if (frame~=nil) then
        LyLock_SetFontHeight(frame, size)
        if visible then
            frame:Show();
        else
            frame:Hide();
        end
    end
end

function LyLock_SetFontHeight(frame, size)
    if (frame~=nil) then frame:SetFont("Fonts\\FRIZQT__.TTF", size, "outline='NORMAL'") end
end

--------------------------------------------------------------------------------------
-- LyLock Main Functions -------------------------------------------------------------
--------------------------------------------------------------------------------------


function LyLock_OnLoad()
    if LyLock_OnSettings("default") then

        this:RegisterEvent("VARIABLES_LOADED");
        this:RegisterEvent("PLAYER_ENTERING_WORLD");
        this:RegisterEvent("PLAYER_LEAVING_WORLD");
        this:RegisterEvent("LEARNED_SPELL_IN_TAB");

        SlashCmdList["LyLock"] = LyLock_AddOnHandler;
        SLASH_LyLock1 = "/lylock";

        SlashCmdList["L"] = L_AddOnHandler;
        SLASH_L1 = "/L";
    end
end

function L_AddOnHandler(msg)
    WhisperWarlocks2(LyLock_PlayerName, msg)
end


function LyLock_OnEvent(event, arg1, arg2, arg3, arg4, arg5)
    if event=="VARIABLES_LOADED" then
        if LyLock_OnSettings("default") then
            LyLock_ApplyVisualSettings()
            EchoColor("LyLock", COLOR_HEADER, LYLOCK_VERSION.." Loaded.  For configuration type /LyLock")
        end
    elseif event=="LEARNED_SPELL_IN_TAB" then
        LyLock_SetupActions()
    elseif event=="PLAYER_ENTERING_WORLD" then
        LyLock_SetupActions()
        for i, p in pairs(LyLock_Plugins) do
            if (p.Button~=nil) then
                getglobal(p.Button):RegisterForDrag("LeftButton");
                getglobal(p.Button):RegisterForClicks("AnyUp");
                getglobal(p.Button):SetScript("OnDragStart", LyLock_Button_OnDragStart)
                getglobal(p.Button):SetScript("OnDragStop", LyLock_Button_OnDragStop)
                getglobal(p.Button):SetScript("OnMouseUp", LyLock_Button_OnMouseUp)
                getglobal(p.Button):SetScript("OnMouseDown", LyLock_Button_OnMouseDown)
                getglobal(p.Button):SetScript("OnEnter", LyLock_Button_OnEnter)
                getglobal(p.Button):SetScript("OnLeave", LyLock_Button_OnLeave)
            end
        end
        for i, p in pairs(LyLock_Plugins) do
            if (p.OnLoad~=nil) then p.OnLoad() end
        end
        for i, p in pairs(LyLock_Plugins) do
            if (p.Events~=nil) and (p.Frame~=nil) and (p.OnEvent~=nil) then
                for i,event in pairs(p.Events) do
                    getglobal(p.Frame):RegisterEvent(event)
                    getglobal(p.Frame):SetScript("OnEvent", p.OnEvent)
                end
            end
        end
        LyLock_ApplyVisualSettings()
    elseif event=="PLAYER_LEAVING_WORLD" then
        for i, p in pairs(LyLock_Plugins) do
            if (p.OnUnload~=nil) then p.OnUnload() end
        end
        for i, p in pairs(LyLock_Plugins) do
            if (p.Events~=nil) and (p.Frame~=nil) and (p.OnEvent~=nil) then
                for i,event in pairs(p.Events) do
                    getglobal(p.Frame):UnregisterEvent(event)
                    getglobal(p.Frame):SetScript("OnEvent", nil)
                end
            end
        end
    end
end


--mainPlayerList = {}
--mainIsParty = false
--mainGroupCount = 0
LyLock_Tooltip_Visible = nil

LyLock_UpdateHalfSec = GetTime()
LyLock_UpdateSecond = GetTime()
function LyLock_OnUpdate()
    if ((GetTime()-LyLock_UpdateHalfSec)>=.5) then
        LyLock_UpdateHalfSec = GetTime()
        for i, p in pairs(LyLock_Plugins) do
            if (p.OnHalfSecond~=nil) then p.OnHalfSecond() end
        end
        
        
--~         local playerList = {}
--~         local isParty = false
--~         local groupCount = GetNumRaidMembers()
--~         if (groupCount>0) then
--~             --We are in a Raid Group
--~             for i=1, MAX_RAID_MEMBERS do
--~                 local name = UnitName("raid"..ii)
--~                 if name~=nil and name~=LyLock_PlayerName then
--~                     AddPlayerInfo(playerList, "raid"..i, name)
--~                 elseif name==LyLock_PlayerName then
--~                     Echo("Your name is in the raid")                
--~                 end
--~             end
--~         else
--~             groupCount = GetNumPartyMembers()
--~             isParty = (mainGroupCount>0)
--~             if isParty then
--~                 -- We are in a Party Group
--~                 for i=1, MAX_PARTY_MEMBERS  do
--~                     local name = UnitName("party"..i)
--~                     if name~=nil and name~=LyLock_PlayerName then
--~                         AddPlayerInfo(playerList, "party"..i, name)
--~                     elseif name==LyLock_PlayerName then
--~                         Echo("Your name is in the party")
--~                     end
--~                 end
--~             end
--~         end
--~         if not isParty and (groupCount==0) then
--~             --We are not in a raid or group
--~         end
--~         
--~         mainIsParty = isParty
--~         mainGroupCount = groupCount
        
    end
    
    if ((GetTime()-LyLock_UpdateSecond)>=1) then         
        LyLock_UpdateSecond = GetTime()
        for i, p in pairs(LyLock_Plugins) do       
            if (p.OnSecond~=nil) then 
                p.OnSecond()
            end
        end
        
        if LyLock_Tooltip_Visible then
            if (LyLock_Tooltip_Visible.ButtonTooltipText~=nil) then
                if LyLock_Settings.Visual_LockFrames then
                    LyLock_ButtonTooltip(LyLock_Tooltip_Visible.Button, LyLock_Tooltip_Visible.ButtonTooltipText())        
                end
            end
        end
    end
end

function AddPlayerInfo(tbl, unit, name)
    local info = {}
    info.Unit = unit
    info.Name = name
    info.HasSS = IsUnitSoulstoned(unit)
end

function LyLock_Button_OnDragStart()
    DEFAULT_CHAT_FRAME:AddMessage("|CFFFF0000Trying to drag LyLock action bar...");
    if (not LyLock_Settings.Visual_LockFrames) then
        DEFAULT_CHAT_FRAME:AddMessage("|CFFFF0000Dragging LyLock action bar...");
            LyLock_Tooltip_Visible = nil
            GameTooltip:Hide();
        LyLockActionBar:StartMoving();
    end
end
function LyLock_Button_OnDragStop()
    LyLockActionBar:StopMovingOrSizing();
end

function LyLock_Button_OnMouseUp()
    LyLockActionBar:StopMovingOrSizing();
    if LyLock_Settings.Visual_LockFrames then
        for i, p in pairs(LyLock_Plugins) do
            if (this:GetName()==p.Button) then
                if (p.ButtonOnMouseUp~=nil) then p.ButtonOnMouseUp() end
            end
        end
    end
end

function LyLock_Button_OnMouseDown()
    if LyLock_Settings.Visual_LockFrames then
        for i, p in pairs(LyLock_Plugins) do
            if (this:GetName()==p.Button) then
                if (p.ButtonOnMouseDown~=nil) then p.ButtonOnMouseDown() end
            end
        end
    end
end

function LyLock_Button_OnEnter()
    for i, p in pairs(LyLock_Plugins) do
        if (this:GetName()==p.Button) then
            if LyLock_Settings.Visual_LockFrames then
                if (p.ButtonTooltipText~=nil) then
                    LyLock_Tooltip_Visible = p
                    LyLock_ButtonTooltip(p.Button, p.ButtonTooltipText())
                end
            else
                LyLock_ButtonTooltip(p.Button, COLOR_LIGHTORANGE.."The buttons are disabled when unlocked\nTo move hold the mouse button and drag")
            end
        end
    end
end

function LyLock_Button_OnLeave()
    LyLock_Tooltip_Visible = nil
    GameTooltip:Hide();
    for i, p in pairs(LyLock_Plugins) do
        if (this:GetName()==p.Button) then
            getglobal(p.Button):Enable()
        end
    end
end

function LyLock_AddOnHandler(msg)
    LyLock_SettingsFrameAction("Open");
end

function LyLock_SetupActions()
    for i, p in pairs(LyLock_Plugins) do
        if (p.ButtonSetupAction~=nil) then p.ButtonSetupAction() end
    end
end


function LyLock_ClearActions()
    for i, p in pairs(LyLock_Plugins) do
        if (p.Button~=nil) then LyLock_SetActionNone(getglobal(p.Button)) end
    end
end

function LyLock_SetupActions()
    for i, p in pairs(LyLock_Plugins) do
        if (p.ButtonSetupAction~=nil) then p.ButtonSetupAction() end
    end
end

function LyLock_SetupActionStone(btn, word, spell, item)
    btn:SetAttribute("type", "macro");
    btn:SetAttribute("shift-type*", "spell");

    local ret = LyLock_SetupActionStone2(btn, spell[1], item[1])
    if not ret then ret = LyLock_SetupActionStone2(btn, spell[2], item[2]) end
    if not ret then ret = LyLock_SetupActionStone2(btn, spell[3], item[3]) end
    if not ret then ret = LyLock_SetupActionStone2(btn, spell[4], item[4]) end
    if not ret then ret = LyLock_SetupActionStone2(btn, spell[5], item[5]) end
    if not ret then ret = LyLock_SetupActionStone2(btn, spell[6], item[6]) end
    if not ret then ret = LyLock_SetupActionStone2(btn, spell[7], item[7]) end
    if not ret then ret = LyLock_SetupActionStone2(btn, spell[8], item[8]) end
end

function LyLock_SetupActionStone2(btn, spell, item)
    if GetSpellRank(spell)~=nil then
        btn:SetAttribute("spell", spell)
        btn:SetAttribute("macrotext", "/stopcasting \n/use "..item)
        return true
    else
        return false
    end
end
function LyLock_SetActionNone(btn)
    btn:SetAttribute("type", "");
    btn:SetAttribute("shift-type*", "");
end

function LyLock_ButtonTooltip(button, text)
    if (text) then
        GameTooltip:SetOwner(getglobal(button), "ANCHOR_CURSOR");
        --LyLock_SetFontHeight(getglobal("GameTooltipTextLeft1"), 12)
        GameTooltip:SetText(text);
    end
end

--------------------------------------------------------------------------------------
-- Message Functions -----------------------------------------------------------------
--------------------------------------------------------------------------------------
function LyMsg(str, tar)
    return strvars(str, tar)
end

function WhisperWarlocks2(toplayer, msg)
    if GetNumRaidMembers()>0 then
        for i=1, MAX_RAID_MEMBERS do
            name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i)
            WhisperWarlock(toplayer, name, class, msg)
        end
    elseif GetNumPartyMembers()>0 then
        for i=1, MAX_PARTY_MEMBERS  do
            local name = UnitName("party"..i)
            WhisperWarlock(toplayer, UnitName("party"..i), UnitClass("party"..i), msg)
        end
    end
end

function WhisperWarlock2(toplayer, name, class, msg)
    if name~=nil then
        if class==WORD_WARLOCK then
            if (name~=toplayer) then
                WhisperName(name, msg)
            end
        end
    end
end

function WhisperWarlocks(toplayer, msg)
    if GetNumRaidMembers()>0 then
        for i=1, MAX_RAID_MEMBERS do
            name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i)
            WhisperWarlock(toplayer, name, class, msg)
        end
    elseif GetNumPartyMembers()>0 then
        for i=1, MAX_PARTY_MEMBERS  do
            local name = UnitName("party"..i)
            WhisperWarlock(toplayer, UnitName("party"..i), UnitClass("party"..i), msg)
        end
    end
end

function WhisperWarlock(toplayer, name, class, msg)
    if name~=nil then
        if class==WORD_WARLOCK then
            if (name~=toplayer) or ((name==toplayer) and (not LyLock_Settings.Soulstone_Whisper)) then
                WhisperName(name, msg)
            end
        end
    end
end

